package com.maozzi.api.es;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.maozzi.api.es.model.EsUserDTO;
import com.maozzi.api.es.repository.EsUserMapper;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.index.query.QueryBuilders;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.elasticsearch.core.query.Query;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.*;

/**
 * es service，DSL 语法
 * <p>
 * 2种方式操作实现es crud
 * 1. 通过 ElasticsearchRestTemplate，适用于较复杂 DSL
 * 2. 通过 ElasticsearchRepository，提供简单 DSL
 *
 * @author maozi
 */
@Service
@Slf4j
public class EsService {
    @Resource
    private ElasticsearchRestTemplate elasticsearchRestTemplate;

    @Resource
    private EsUserMapper esUserMapper;

    /**
     * es index name
     */
    @Value("${elasticsearch.index}")
    private String index;

    private final static Gson GSON = new Gson();

    /**
     * 通过 ElasticsearchRestTemplate 搜索
     *
     * @param keyword 关键字
     * @return 返回
     */
    public List<EsUserDTO> searchByTemplate(String keyword) {
        List<EsUserDTO> list = new ArrayList<>();
        try {
            // 这里es索引是可以传多个的
            IndexCoordinates coordinates = IndexCoordinates.of(index);

            NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();

            // 精确匹配
            if (StringUtils.hasText(keyword)) {
                // "name", keyword
                builder.withQuery(QueryBuilders.termQuery("name", keyword));
            }

            // 分页
            // PageRequest pageRequest = PageRequest.of(page,pageNum);

            Query query = builder.build();
            SearchHits<Object> hits = elasticsearchRestTemplate.search(query, Object.class, coordinates);

            // SearchHitSupport.searchPageFor(hits,pageRequest);

            for (SearchHit<Object> hit : hits.getSearchHits()) {
                String id = hit.getId();
                if ("%{id}".equals(id)) {
                    continue;
                }

                String json = GSON.toJson(hit.getContent());
                if (Objects.isNull(json) || json.isBlank()) {
                    continue;
                }

                Map<String, Object> map = GSON.fromJson(json, new TypeToken<>() {
                });
                Long dtoId = Double.valueOf(String.valueOf(map.get("id"))).longValue();
                String name = String.valueOf(map.get("name"));
                String avatar = String.valueOf(map.get("avatar"));
                Byte type = Double.valueOf(String.valueOf(map.get("type"))).byteValue();
                EsUserDTO dto = new EsUserDTO(dtoId, name, avatar, type);

                list.add(dto);
            }
        } catch (Exception e) {
            log.error("EsService searchByTemplate => param[keyword]={}", keyword, e);
        }

        return list;
    }

    /**
     * 通过 ElasticsearchRepository 搜索
     *
     * @param keyword 关键字
     * @return 返回
     */
    public List<EsUserDTO> searchByRepo(String keyword) {
        List<EsUserDTO> list = new ArrayList<>();
        try {
            EsUserDTO dto = new EsUserDTO().setName(keyword);

            // 分页
//            PageRequest pageRequest = PageRequest.of(1, 10);

//             esUserMapper.findAll(pageRequest);
            Iterable<EsUserDTO> all = esUserMapper.findAll();
            for (EsUserDTO esUserDTO : all) {
                list.add(esUserDTO);
            }
        } catch (Exception e) {
            log.error("EsService searchByRepo => param[keyword]={}", keyword, e);
        }

        return list;
    }
}
